package com.diy.common.dao;

import com.diy.common.helper.StringUtil;
import com.diy.common.baseModel.Paging;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;

import java.util.List;
import java.util.Map;

/**
 * Created by GY on 2015/11/22.
 */
//@Repository
public class DaoImpl implements Dao {

//    @Autowired
    protected SqlSession sqlSession;

    // ----------------------------------------------------------------------------------------------------

    public <T> T selectOne(String statement) {
        checkStatement(statement);
        return sqlSession.selectOne(statement);
    }

    public <T> T selectOne(String statement, Object parameter) {
        checkStatement(statement);
        checkParameter(parameter);
        return sqlSession.selectOne(statement, parameter);
    }

    public <E> List<E> selectList(String statement) {
        checkStatement(statement);
        return sqlSession.selectList(statement);
    }

    public <E> List<E> selectList(String statement, Object parameter) {
        checkStatement(statement);
        checkParameter(parameter);
        return sqlSession.selectList(statement, parameter);
    }

    public <E> List<E> selectList(String statement, int pageNumber, int pageSize) {
        checkStatement(statement);
        checkPageNumber(pageNumber);
        checkPageSize(pageSize);
        RowBounds rowBounds = createRowBounds(pageNumber, pageSize);
        return sqlSession.selectList(statement, null, rowBounds);
    }

    public <E> List<E> selectList(String statement, Object parameter, int pageNumber, int pageSize) {
        checkStatement(statement);
        checkParameter(parameter);
        checkPageNumber(pageNumber);
        checkPageSize(pageSize);
        RowBounds rowBounds = createRowBounds(pageNumber, pageSize);
        return sqlSession.selectList(statement, parameter, rowBounds);
    }

    public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
        checkStatement(statement);
        checkMapKey(mapKey);
        return sqlSession.selectMap(statement, mapKey);
    }

    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
        checkStatement(statement);
        checkParameter(parameter);
        checkMapKey(mapKey);
        return sqlSession.selectMap(statement, parameter, mapKey);
    }

    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, int pageNumber, int pageSize) {
        checkStatement(statement);
        checkParameter(parameter);
        checkMapKey(mapKey);
        RowBounds rowBounds = createRowBounds(pageNumber, pageSize);
        return sqlSession.selectMap(statement, parameter, mapKey, rowBounds);
    }

    public <T> Paging<T> selectPaging(String statement, int pageNumber, int pageSize) {
        checkStatement(statement);
        checkPageNumber(pageNumber);
        checkPageSize(pageSize);
        List<T> itemList = selectList(statement, pageNumber, pageSize);
        int totalCount = TotalCountContainer.get();
        TotalCountContainer.remove();
        return new Paging<T>(pageNumber, pageSize, totalCount, itemList);
    }


    public <T> Paging<T> selectPaging(String statement, Object parameter, int pageNumber, int pageSize) {
        checkStatement(statement);
        checkParameter(parameter);
        checkPageNumber(pageNumber);
        checkPageSize(pageSize);
        List<T> itemList = selectList(statement, parameter, pageNumber, pageSize);
        int totalCount = TotalCountContainer.get();
        TotalCountContainer.remove();
        return new Paging<T>(pageNumber, pageSize, totalCount, itemList);
    }

    // ----------------------------------------------------------------------------------------------------

    public int insert(String statement) {
        checkStatement(statement);
        return sqlSession.insert(statement);
    }

    public int insert(String statement, Object parameter) {
        checkStatement(statement);
        checkParameter(parameter);
        return sqlSession.insert(statement, parameter);
    }

    // ----------------------------------------------------------------------------------------------------

    public int update(String statement) {
        checkStatement(statement);
        return sqlSession.update(statement);
    }

    public int update(String statement, Object parameter) {
        checkStatement(statement);
        checkParameter(parameter);
        return sqlSession.update(statement, parameter);
    }

    // ----------------------------------------------------------------------------------------------------

    public int delete(String statement) {
        checkStatement(statement);
        return sqlSession.delete(statement);
    }

    public int delete(String statement, Object parameter) {
        checkStatement(statement);
        checkParameter(parameter);
        return sqlSession.delete(statement, parameter);
    }

    // ----------------------------------------------------------------------------------------------------

    private void checkStatement(String statement) {
        if (StringUtil.isEmpty(statement)) {
            throw new IllegalArgumentException("argument [statement] is empty");
        }
    }

    private void checkParameter(Object parameter) {
        if (parameter == null) {
            throw new IllegalArgumentException("argument [parameter] is null");
        }
    }

    private void checkPageNumber(int pageNumber) {
        if (pageNumber <= 0) {
            throw new IllegalArgumentException("argument [pageNumber] is illegal");
        }
    }

    private void checkPageSize(int pageSize) {
        if (pageSize <= 0) {
            throw new IllegalArgumentException("argument [pageSize] is illegal");
        }
    }

    private void checkMapKey(String mapKey) {
        if (StringUtil.isEmpty(mapKey)) {
            throw new IllegalArgumentException("argument [mapKey] is empty");
        }
    }

    private RowBounds createRowBounds(int pageNumber, int pageSize) {
        return new RowBounds((pageNumber - 1) * pageSize, pageSize);
    }
}
